/**
 * 存储工厂
 *
 * 自动选择合适的存储实现并处理数据迁移
 */

import { db, initializeDatabase } from './indexedDB/database'
import { IndexedDBAdapter } from './indexedDB/indexedDBAdapter'
import { StorageMigrator } from './migration/migrator'
import { localStorageAdapter } from './storageAdapter'
import type { StorageAdapter } from './types'

/**
 * 存储工厂类
 * 单例模式,全局共享存储实例
 */
export class StorageFactory {
  private static adapter: IndexedDBAdapter | StorageAdapter | null = null
  private static initPromise: Promise<IndexedDBAdapter | StorageAdapter> | null = null

  /**
   * 初始化存储
   * 优先级: IndexedDB > LocalStorage
   */
  static async initialize(): Promise<IndexedDBAdapter | StorageAdapter> {
    // 如果已经初始化,直接返回
    if (this.adapter) {
      console.log('[存储工厂] 使用已初始化的适配器')
      return this.adapter
    }

    // 如果正在初始化,等待初始化完成
    if (this.initPromise) {
      console.log('[存储工厂] 等待初始化完成...')
      return this.initPromise
    }

    // 开始新的初始化
    this.initPromise = this._doInitialize()
    return this.initPromise
  }

  /**
   * 实际执行初始化
   */
  private static async _doInitialize(): Promise<IndexedDBAdapter | StorageAdapter> {
    console.log('[存储工厂] 开始初始化存储...')

    try {
      // 1. 尝试初始化IndexedDB
      console.log('[存储工厂] 尝试IndexedDB...')
      const indexedDBAvailable = await initializeDatabase()

      if (!indexedDBAvailable) {
        console.warn('[存储工厂] IndexedDB不可用,降级到LocalStorage')
        this.adapter = localStorageAdapter
        return this.adapter
      }

      // 2. 检查是否需要迁移
      const needsMigration = await StorageMigrator.checkMigrationNeeded()

      if (needsMigration) {
        console.log('[存储工厂] 检测到LocalStorage数据,开始迁移...')
        const migrator = new StorageMigrator(db, {
          validateAfterMigration: true,
          clearLocalStorageAfterMigration: false  // 保留LocalStorage数据作为备份
        })

        const migrationResult = await migrator.migrate()

        if (!migrationResult.ok) {
          console.error('[存储工厂] ❌ 迁移失败,降级到LocalStorage', migrationResult.error)
          this.adapter = localStorageAdapter
          return this.adapter
        }

        console.log('[存储工厂] ✅ 迁移成功:', migrationResult.data)
      }

      // 3. 使用IndexedDB
      this.adapter = new IndexedDBAdapter(db)
      console.log('[存储工厂] ✅ 使用IndexedDB存储')

      // 4. 测试连接
      const testResult = await this.adapter.listRecent(1)
      if (!testResult.ok) {
        console.error('[存储工厂] IndexedDB连接测试失败,降级到LocalStorage')
        this.adapter = localStorageAdapter
        return this.adapter
      }

      console.log('[存储工厂] ✅ IndexedDB连接测试成功')
      return this.adapter
    } catch (error) {
      console.error('[存储工厂] ❌ 初始化失败,降级到LocalStorage', error)
      this.adapter = localStorageAdapter
      return this.adapter
    } finally {
      // 清除initPromise,允许重新初始化
      this.initPromise = null
    }
  }

  /**
   * 获取当前适配器
   * 如果未初始化,会抛出错误
   */
  static getAdapter(): IndexedDBAdapter | StorageAdapter {
    if (!this.adapter) {
      throw new Error('[存储工厂] 存储未初始化,请先调用 initialize()')
    }
    return this.adapter
  }

  /**
   * 检查是否使用IndexedDB
   */
  static isUsingIndexedDB(): boolean {
    return this.adapter instanceof IndexedDBAdapter
  }

  /**
   * 检查是否使用LocalStorage
   */
  static isUsingLocalStorage(): boolean {
    return this.adapter === localStorageAdapter
  }

  /**
   * 获取当前存储类型
   */
  static getStorageType(): 'indexeddb' | 'localstorage' | 'unknown' {
    if (this.isUsingIndexedDB()) return 'indexeddb'
    if (this.isUsingLocalStorage()) return 'localstorage'
    return 'unknown'
  }

  /**
   * 强制重新初始化
   * 仅用于测试或特殊情况
   */
  static async reinitialize(): Promise<IndexedDBAdapter | StorageAdapter> {
    console.log('[存储工厂] ⚠️ 强制重新初始化')
    this.adapter = null
    this.initPromise = null
    return this.initialize()
  }

  /**
   * 重置工厂(仅用于测试)
   */
  static reset(): void {
    console.log('[存储工厂] ⚠️ 重置工厂')
    this.adapter = null
    this.initPromise = null
  }
}

/**
 * 便捷函数: 获取存储实例
 * 会自动初始化
 */
export async function getStorage(): Promise<IndexedDBAdapter | StorageAdapter> {
  return StorageFactory.initialize()
}

/**
 * 便捷函数: 获取已初始化的存储实例
 * 如果未初始化,会抛出错误
 */
export function getStorageSync(): IndexedDBAdapter | StorageAdapter {
  return StorageFactory.getAdapter()
}
